<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>设备状态监控系统</title>
    <script src="../assets/vue.js"></script>
    <script src="../assets/axios.min.js"></script>
    <link rel="stylesheet" href="./zzt.css">
</head>
<body>
    <div id="app">
        <div class="storage-indicator" v-if="persistedComputerCount > 0">
            已加载 {{ persistedComputerCount }} 个保存的设备
        </div>
        <div class="overlay" :class="{'active': settingsActive || alarmDetailsVisible || showDeleteConfirmation || showColorPicker}" 
             @click="closeAllPanels"></div>

        <!-- 新增：声音类型切换按钮 -->
        <button class="sound-type-toggle" :class="soundType" @click="toggleSoundType" :disabled="isSwitchingSoundType">
            {{ soundType === 'audio' ? '音频播报' : '语音播报' }}
            <span v-if="isSwitchingSoundType" class="speech-status">切换中...</span>
        </button>

        <div class="alarm-icon" :class="{'active': activeProtectionCount > 0}" @click="toggleAlarmDetails">
            🔔 <span v-if="activeProtectionCount > 0" class="alert-indicator" 
                    style="position:absolute; top:-2px; right:-2px;"></span>
        </div>
        <div class="settings-btn" @click="toggleSettingsPanel">⚙️</div>
        <div class="settings-panel" :class="{'active': settingsActive}">
            <div class="settings-header">
                <h2 class="settings-title">系统设置</h2>
                <button class="settings-close" @click="toggleSettingsPanel">×</button>
            </div>
            
            <!-- 系统参数设置 -->
            <div class="settings-group">
                <h3 class="settings-group-title">系统参数</h3>
                <div class="settings-item">
                    <label class="settings-label">长轮询超时时间（秒）</label>
                    <input type="number" class="settings-input" v-model.number="settings.longPollTimeout" :disabled="isSavingSettings" step="1" min="5" max="60">
                </div>

                <div class="settings-item">
                    <label class="settings-label">数据持久化</label>
                    <div class="form-hint">
                        当前已保存 {{ persistedComputerCount }} 台设备
                    </div>
                </div>
            </div>
            <!--开机自启动按钮-->
            <div class="settings-group">
                <div class="settings-group-title">开机自启动设置</div>
                <label class="switch">
                  <input type="checkbox" id="autoStartToggle">
                  <span class="slider"></span>
                </label>
                <span id="autoStartStatus">加载中...</span>
            </div>
            
            <!-- 已删除设备管理 - 优化部分 -->
            <div class="settings-group">
                <h3 class="settings-group-title">已删除设备管理</h3>
                <div v-if="hasDeletedEquipments" class="deleted-equipments-container">
                    <div class="deleted-equipments-scroll">
                        <div v-for="(equipments, computerName) in sortedDeletedEquipments" :key="computerName" class="deleted-computer-group">
                            <div class="deleted-computer-name">
                                {{ computerName }}
                                <span class="equipment-count">{{ equipments.length }} 个设备</span>
                            </div>
                            <div class="deleted-equipments-grid">
                                <div v-for="equipmentCode in equipments" :key="equipmentCode" class="deleted-equipment-item">
                                    <span>设备 {{ equipmentCode }}</span>
                                    <button class="equipment-restore-btn" @click="restoreEquipment(computerName, equipmentCode)">
                                        恢复
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div v-else class="form-hint">没有已删除的设备</div>
            </div>
             
            <!-- 自定义数据发送 -->
            <div class="settings-group">
                <h3 class="settings-group-title">Lims系统URL路径编辑</h3>
                <input class="config-textarea" v-model="configFileContent" placeholder="在此编辑URL路径...">
                
                <div class="config-buttons">
                    <button class="config-btn config-open-btn" @click="openConfigFile">打开配置文件</button>
                </div>
                
                <div class="config-path-info" v-if="currentConfigPath">
                    当前配置文件: {{ currentConfigPath }}
                </div>
            </div>


            <div class="settings-footer">
                <button class="settings-save-btn" @click="saveSettings" :disabled="isSavingSettings">
                    <span v-if="isSavingSettings">保存中...</span>
                    <span v-else>保存设置</span>
                </button>
            </div>
        </div>
        <div class="alarm-details-panel" v-if="alarmDetailsVisible">
            <div class="alarm-details-header">
                <h2 class="alarm-details-title">报警详细信息</h2>
                <label class="dont-show-again">
                    <input type="checkbox" class="dont-show-checkbox" v-model="dontShowAlarmDetails">
                    不再自动显示报警详情
                </label>
                <button class="close-btn" @click="toggleAlarmDetails">×</button>
            </div>
            <table class="alarm-table">
                <thead>
                    <tr>
                        <th>起始时间</th>
                        <th>电脑名</th>
                        <th>设备号</th>
                        <th>通道号</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="record in historyRecords" :key="record.id">
                        <td>{{ record.displayTime }}</td>
                        <td>{{ record.pcName }}</td>
                        <td>{{ record.equiptCode }}</td>
                        <td>{{ record.channelCode }}</td>
                    </tr>
                </tbody>
            </table>
            <div class="alarm-details-footer">
                <div class="col-12 pd-4">
                    <div class="line"></div>
                </div>
                <div class="col-md text-md-left">
                    <ul class="list-unstyled link-menu nav-left">
                        <li>
                            <a href="#">Privacy Policy</a>
                        </li>
                        <li>
                            <a href="#">Terms & Conditions</a>
                        </li>
                        <li>
                            <a href="#">Code of Conduct</a>
                        </li>
                    </ul>
                </div>
                <div class="col-md-6 text-md-right">
                    <ul class="list-unstyled social nav-right">
                        <li>
                            <a href="#">
                                <img src="../assets/feishu (1).svg" alt="飞书图标">
                            </a>
                        </li>
                        <li>
                            <a href="#">
                                <img src="../assets/youjian.svg" alt="邮件图标">
                            </a>
                        </li>
                        <li>
                            <a href="#">
                                <img src="../assets/qiyeweixin.svg" alt="企业微信图标">
                            </a>
                        </li>
                    </ul>
                
                </div>
                <div class="row">
                    <div class="col-md-7">
                        <p>
                            <small>
                                Innovation drives the progress of the new energy world.
                            </small>
                        </p>
                    </div>
                </div>
                <div class="col-md-8">
                    <p>
                        <small>
                            © 2025 All Rights Reserved.
                        </small>
                    </p>
                </div>
            </div>
        </div>    
        <div class="confirmation-dialog" v-if="showDeleteConfirmation">
            <div class="confirmation-message">
                确定要删除电脑 "{{ computerToDelete }}" 吗?
            </div>
            <div class="confirmation-buttons">
                <button class="confirmation-btn cancel-btn" @click="showDeleteConfirmation = false">取消</button>
                <button class="confirmation-btn confirm-btn" @click="confirmDeleteComputer">确定</button>
            </div>
        </div>
        <div class="confirmation-dialog" v-if="showDeleteConfirmation && deleteTarget === 'equipment'">
            <div class="confirmation-message">
                确定要删除{{ deleteTarget === 'computer' ? '电脑' : '设备' }} "{{ deleteTargetName }}" 吗?
                <div class="form-hint" style="margin-top: 10px; color: #666;">可在设置中恢复已删除的设备</div>
            </div>
            <div class="confirmation-buttons">
                <button class="confirmation-btn cancel-btn" @click="showDeleteConfirmation = false">取消</button>
                <button class="confirmation-btn confirm-btn" @click="confirmDelete">确定</button>
            </div>
        </div>
        <div class="color-picker-container" v-if="showColorPicker">
            <div class="color-picker-dialog">
                <h3 class="color-picker-title">设置 {{ currentStatus }} 状态颜色</h3>
                <input type="color" class="color-picker-input" v-model="tempColor">
                <div class="color-picker-buttons">
                    <button class="color-picker-btn color-picker-cancel" @click="cancelColorChange">取消</button>
                    <button class="color-picker-btn color-picker-save" @click="saveColorChange">保存</button>
                </div>
            </div>
        </div>              
        <button 
            v-if="activeProtectionCount > 0"
            class="sound-control-btn"
            :class="{'resolved': resolvedAll}"
            @click="resolveAllAlarms"
        >
            <span class="sound-icon">🔕</span>
            消除报警
        </button>
        <div class="app">            
            <div class="sidebar">
                <div class="page-title">设备状态监控系统</div>
                <div class="header">
                    <h1>设备管理</h1>
                </div>               
                <div class="add-computer-form">
                    <div class="form-group">
                        <input
                            type="text"
                            class="form-input"
                            placeholder="输入电脑名 (如 CTRC-534)"
                            v-model="newComputerName"
                            @input="newComputerName = newComputerName.toUpperCase()"
                            @keyup.enter="addComputer"
                        >
                        <button class="form-btn" @click="addComputer">添加</button>
                    </div>
                    <div class="error-message" v-if="errorMessage">{{ errorMessage }}</div>
                </div>
                <div 
                    class="all-channels-btn" 
                    @click="showAllChannels"
                    :class="{'active': viewMode === 'all'}"
                >
                    查看所有通道
                </div>
                <div class="computer-list" @dragover.prevent @dragenter.prevent>
                    <h3 v-if="monitoredComputers.length === 0" class="form-hint">请添加要监控的电脑</h3>
                    <div 
                        class="computer-item" 
                        v-for="(computer, index) in monitoredComputers" 
                        :key="computer.name"
                        :class="{
                            'computer-item-protected': hasProtectionStatus(computer.name) || 
                                                      computerStatusMap[computer.name] === '掉线'
                        }"
                        :data-index="index"
                        draggable="true"
                        @dragstart="onDragStart($event, index)"
                        @dragover="onDragOver($event, index)"
                        @dragenter="onDragEnter($event, index)"
                        @dragleave="onDragLeave($event, index)"
                        @dragend="onDragEnd($event, index)"
                        @drop="onDrop($event, index)"
                    >
                        <div class="computer-header">
                            <div class="computer-name" @click="toggleComputer(computer)">
                                <span v-if="hasProtectionStatus(computer.name) || computerStatusMap[computer.name] === '掉线'" 
                                      class="alert-indicator"></span>
                                {{ computer.name }}
                            </div>
                            
                            <!-- 备注输入框 + 状态标记 -->
                            <div style="display: flex; align-items: center;">
                                <input
                                    type="text"
                                    class="computer-note-input"
                                    v-model="computer.note"
                                    placeholder="输入备注"
                                    title="点击输入备注"
                                    @input="saveMonitoredComputers"
                                >
                                <span class="status-indicator status-disconnected" 
                                      v-if="computer.status === '掉线'">掉线</span>
                            </div>
                            
                            <button class="delete-btn" @click="initiateDeleteComputer(computer.name)">删除</button>
                        </div>
                        <div class="equipment-codes" v-if="computer.expanded">
                            <div 
                                v-for="equipment in getEquipmentByComputer(computer.name)" 
                                :key="equipment.equiptCode"
                                class="equipment-item"
                                :class="{
                                    'selected-equipment': selectedEquipment === equipment.equiptCode && selectedComputer === computer.name,
                                    'equipment-protected': hasProtectionForEquipment(equipment.equiptCode,computer.name)
                                }"
                                @click="selectEquipment(equipment, computer)"
                            >
                                <span class="equipment-code">设备 {{ equipment.equiptCode }}</span>
                                <span v-if="hasProtectionForEquipment(equipment.equiptCode,computer.name)" class="alert-indicator"></span>
                                <!-- 添加设备删除按钮 -->
                                <button class="equipment-delete-btn" @click.stop="initiateDeleteEquipment(computer.name, equipment.equiptCode)">删除</button>
                            </div>
                        </div>
                    </div>
                    <div class="monitored-count" v-if="monitoredComputers.length > 0">
                        监控中设备: {{ monitoredComputers.length }} 个
                    </div>
                </div>
                <div class="footer">
                    最近更新：{{ lastRefreshTime }}<br>
                    长轮询超时: {{ settings.longPollTimeout }}秒
                </div>
            </div>            
            <div class="main-content">
                <div class="status-refresh-time">当前模式: {{ getViewModeName() }}</div>
                <div class="header">
                    <h2 v-if="viewMode === 'device' && selectedEquipment && selectedComputer">
                        {{ selectedComputer }} - 设备 {{ selectedEquipment }} 的通道状态
                    </h2>
                    <h2 v-else-if="viewMode === 'computer' && selectedComputer">
                        {{ selectedComputer }} 的通道状态
                    </h2>
                    <h2 v-else>
                        所有设备的通道状态 ({{ filteredChannels.length }} 个通道)
                    </h2>
                </div>
                
                <!-- 新增状态筛选栏 -->
                <div class="status-filter-bar">
                    <button 
                        class="status-btn" 
                        v-for="status in statusList" 
                        :key="status"
                        @click="openColorPicker(status)"
                        :style="{ backgroundColor: statusColors[status].bgColor }"
                    >
                        <div class="status-color-preview" :style="{ backgroundColor: statusColors[status].bgColor }"></div>
                        {{ status }}
                    </button>
                    <div class="server-info-panel">
                        <div class="stats-container">
                            <div class="stat-item">
                                <div class="stat-label">活动报警</div>
                                <div class="stat-value">{{ activeProtectionCount }} 个</div>
                            </div>
                            <div class="stat-item">
                                <div class="stat-label">通道总数</div>
                                <div class="stat-value">{{ filteredChannels.length }}</div>
                            </div>
                            <div class="stat-item">
                                <div class="stat-label">监控电脑</div>
                                <div class="stat-value">{{ monitoredComputers.length }}</div>
                            </div>
                            <div class="stat-item">
                                <div class="stat-label">更新时间</div>
                                <div class="stat-value">{{ lastRefreshTime }}</div>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="scroll-container">
                    <div class="channel-grid">
                        <div 
                            v-for="channel in filteredChannels" 
                            :key="channel.key" 
                            class="channel-card"
                            :class="{
                                'channel-protected': channel.systemStatus === '保护' && !channel.resolved,
                                'channel-resolved': channel.resolved,
                                'channel-offline': channel.systemStatus === '离线',
                                'channel-disconnected': channel.computerStatus === '掉线' || channel.systemStatus === '掉线'
                            }"
                            :style="getStatusStyle(channel.systemStatus)"
                        >
                            <div class="channel-header">
                                <div class="channel-title">
                                    {{ channel.pcName }}_{{ channel.equiptCode }}_{{ channel.channelCode }}
                                </div>
                            </div>
                            <div 
                                class="status-text" 
                                :class="{
                                    'status-text-protection': channel.systemStatus === '保护' && !channel.resolved,
                                    'status-text-resolved': channel.resolved
                                }"
                            >
                                {{ channel.systemStatus }}
                            </div>
                            <div 
                                class="status-bar" 
                                :class="{
                                    'status-protection': channel.systemStatus === '保护' && !channel.resolved,
                                    'status-resolved': channel.resolved
                                }"
                            ></div>
                            <div class="time-info">
                                <span>当前时间: {{ channel.curtime }}</span>
                            </div>
                        </div>
                    </div>
                    <div v-if="filteredChannels.length === 0" class="empty-panel">
                        当前没有可显示的通道数据
                    </div>
                </div>
            </div>
        </div>      
                
        <audio id="alarm-sound" preload="auto" loop>
            <source src="../assets/1123.wav" type="audio/mpeg">
        </audio>
    </div>
    <script>
        const DEFAULT_API_URL = 'http://localhost:5000/get_data';
        const DEFAULT_LONG_POLL_TIMEOUT = 30; // 默认长轮询超时时间30秒
        const STORAGE_KEY = 'monitoredComputers';     
        const STATUS_COLORS_KEY = 'statusColors';
        const SOUND_TYPE_KEY = 'alarmSoundType'; // 新增：声音类型存储键
        const ALARM_DETAILS_KEY = 'dontShowAlarmDetails'; // 新增：报警详情设置存储键
        
        // 优化后的数字提取函数
        function extractNumber(str) {
            const match = str.match(/\d+/);
            return match ? parseInt(match[0]) : 0;
        }    
        
        // 用于排序的自然排序函数
        function naturalSort(a, b) {
            const aNum = extractNumber(a);
            const bNum = extractNumber(b);
            if (aNum !== bNum) {
                return aNum - bNum;
            }
            return a.localeCompare(b);
        }
        
        class ChannelStatusRecorder {
            constructor() {
                this.channelStates = {};    
                this.historyRecords = [];   
                this.recordId = 1;          
                this.channelRecords = {};   
                this.newAlarms = new Set(); // 新增：跟踪新的报警
                this.previousStates = {}; // 新增：跟踪上一次的状态，用于检测状态变化
            }          
            
            getChannelKey(channel) {
                return `${channel.pcName}-${channel.equiptCode}-${channel.channelCode}`;
            }          
            
            updateChannelStatus(channel) {
                const key = this.getChannelKey(channel);
                const isProtected = channel.systemStatus === '保护';
                const currentTime = new Date().getTime();  // 使用当前时间戳
                const previousStatus = this.previousStates[key]; // 获取上一次状态
                
                // 记录当前状态作为下一次的"上一次状态"
                this.previousStates[key] = channel.systemStatus;
                
                if (!this.channelStates[key]) {
                    this.channelStates[key] = {
                        lastStatus: channel.systemStatus,
                        lastChangeTime: currentTime,
                        displayTime: this.formatTime(currentTime)
                    };                   
                    
                    if (isProtected) {
                        this.addHistoryRecord(channel, currentTime);
                        this.newAlarms.add(key); // 标记为新报警
                    }
                    return {
                        statusChanged: false,
                        fromProtection: false
                    };
                }
                
                const channelState = this.channelStates[key];               
                if (channelState.lastStatus !== channel.systemStatus) {
                    // 记录状态变化
                    const fromProtection = channelState.lastStatus === '保护';
                    
                    channelState.lastStatus = channel.systemStatus;
                    channelState.lastChangeTime = currentTime;
                    channelState.displayTime = this.formatTime(currentTime);                  
                    
                    if (isProtected) {
                        this.addHistoryRecord(channel, currentTime);
                        this.newAlarms.add(key); // 标记为新报警
                    } else {
                        this.newAlarms.delete(key); // 状态不再是保护，移除新报警标记
                    }
                    
                    return {
                        statusChanged: true,
                        fromProtection: fromProtection
                    };
                }              
                else if (isProtected) {
                    channelState.displayTime = this.channelStates[key].displayTime;
                }
                
                return {
                    statusChanged: false,
                    fromProtection: false
                };
            }        
            
            getChannelStartTime(channel) {
                const key = this.getChannelKey(channel);
                return this.channelStates[key]?.displayTime || '--:--:--';
            }           
            
            addHistoryRecord(channel, timestamp) {
                const key = this.getChannelKey(channel);              
                
                if (this.channelRecords[key]) {
                    const record = this.channelRecords[key];
                    record.timestamp = timestamp;
                    record.displayTime = this.formatTime(timestamp);
                    return;
                }                
                
                const record = {
                    id: this.recordId++,
                    pcName: channel.pcName,
                    equiptCode: channel.equiptCode,
                    channelCode: channel.channelCode,
                    timestamp: timestamp,
                    displayTime: this.formatTime(timestamp)
                };
                
                this.historyRecords.push(record);
                this.channelRecords[key] = record;
            }          
            
            getHistoryRecords() {
                // 返回按时间倒序的最新10条记录
                return [...this.historyRecords]
                    .sort((a, b) => b.id - a.id)  // 按记录ID排序，保留原始顺序
                    .slice(0, 10);
            }
            
            // 格式化时间显示
            formatTime(timestamp) {
                const date = new Date(timestamp);
                const hours = date.getHours().toString().padStart(2, '0');
                const minutes = date.getMinutes().toString().padStart(2, '0');
                const seconds = date.getSeconds().toString().padStart(2, '0');
                return `${hours}:${minutes}:${seconds}`;
            }
            
            // 新增：获取新报警
            getNewAlarms() {
                return new Set(this.newAlarms);
            }
            
            // 新增：清除新报警标记
            clearNewAlarms() {
                this.newAlarms.clear();
            }
        }
        
        // 优化后的语音播报管理器
        class SpeechManager {
            constructor() {
                this.queue = [];
                this.isSpeaking = false;
                this.synth = window.speechSynthesis;
                this.activeAlarms = new Set(); // 跟踪当前活跃的报警
                this.repeatInterval = 5000; // 重复播报间隔（5秒）
                this.repeatTimers = new Map(); // 存储每个报警的重复计时器
            }
            
            // 添加到播报队列
            addToQueue(text, alarmId) {
                this.queue.push({ text, alarmId });
                this.activeAlarms.add(alarmId);
                
                // 设置重复播报
                if (!this.repeatTimers.has(alarmId)) {
                    const timer = setInterval(() => {
                        if (this.activeAlarms.has(alarmId)) {
                            this.queue.push({ text, alarmId });
                            if (!this.isSpeaking) {
                                this.processQueue();
                            }
                        }
                    }, this.repeatInterval);
                    this.repeatTimers.set(alarmId, timer);
                }
                
                if (!this.isSpeaking) {
                    this.processQueue();
                }
            }
            
            // 处理播报队列
            async processQueue() {
                if (this.queue.length === 0) {
                    this.isSpeaking = false;
                    return;
                }
                
                this.isSpeaking = true;
                const { text, alarmId } = this.queue.shift();
                
                // 检查这个报警是否仍然活跃
                if (!this.activeAlarms.has(alarmId)) {
                    this.processQueue();
                    return;
                }
                
                try {
                    // 等待语音合成完成
                    await this.speak(text);
                } catch (error) {
                    console.error('语音播报错误:', error);
                }
                
                // 继续处理下一个
                this.processQueue();
            }
            
            // 语音合成
            speak(text) {
                return new Promise((resolve, reject) => {
                    if (!this.synth) {
                        reject(new Error('当前浏览器不支持语音合成'));
                        return;
                    }
                    
                    // 停止任何正在进行的语音
                    this.synth.cancel();
                    
                    const utterance = new SpeechSynthesisUtterance(text);
                    utterance.lang = 'zh-CN';
                    utterance.rate = 0.9; // 语速稍慢，便于听清
                    utterance.pitch = 1;
                    utterance.volume = 1;
                    
                    utterance.onend = resolve;
                    utterance.onerror = reject;
                    
                    this.synth.speak(utterance);
                });
            }
            
            // 清除特定报警的重复播报
            clearAlarm(alarmId) {
                this.activeAlarms.delete(alarmId);
                
                // 从队列中移除所有该报警的播报任务
                this.queue = this.queue.filter(item => item.alarmId !== alarmId);
                
                const timer = this.repeatTimers.get(alarmId);
                if (timer) {
                    clearInterval(timer);
                    this.repeatTimers.delete(alarmId);
                }
            }
            
            // 清除所有报警的重复播报
            clearAllAlarms() {
                this.activeAlarms.clear();
                
                // 清空队列
                this.queue = [];
                
                // 清除所有计时器
                this.repeatTimers.forEach(timer => clearInterval(timer));
                this.repeatTimers.clear();
            }
            
            // 清空队列并停止播报
            stop() {
                this.queue = [];
                if (this.synth) {
                    this.synth.cancel();
                }
                this.isSpeaking = false;
            }
            
            // 检查是否正在播报
            isActive() {
                return this.isSpeaking || this.queue.length > 0;
            }
        }
        
        new Vue({
            el: '#app',
            data: {
                rawData: [],                
                lastRefreshTime: '--:--:--', 
                monitoredComputers: [],      
                selectedEquipment: null,
                selectedComputer: null,     
                longPollTimeout: DEFAULT_LONG_POLL_TIMEOUT, // 长轮询超时时间（秒）
                isPolling: false, // 是否正在进行长轮询
                newComputerName: '',        
                errorMessage: '',           
                alarmAudio: null,          
                alarmPlaying: false,        
                viewMode: 'all',            
                alarmDetailsVisible: false, 
                settingsActive: false,      
                settings: {
                    longPollTimeout: DEFAULT_LONG_POLL_TIMEOUT // 长轮询超时时间（秒）
                },
                activeProtectionCount: 0,   
                resolvedChannels: new Set(), 
                statusRecorder: new ChannelStatusRecorder(),
                showDeleteConfirmation: false, 
                computerToDelete: '',       
                soundEnabled: true, // 总是启用声音，不再需要用户手动开启
                resolvedAll: false,
                persistedComputerCount: 0,
                customData: '',
                sendStatusMessage: '',               
                // 电脑状态标记映射
                computerStatusMap: {},
                // 新增拖动相关状态
                isDragging: false,
                dragStartIndex: -1,
                dragOverIndex: -1,
                dragDirection: null, // 标记拖动方向：'top' 或 'bottom'
                
                // 新增状态颜色配置
                statusList: ['充电', '放电', '完成','暂停','保护', '搁置','停止', '离线', '掉线', '其他'],
                statusColors: {
                    '充电': { bgColor: '#90EE90', textColor: '#155724' },
                    '放电': { bgColor: '#FFDEAD', textColor: '#004085' },
                    '完成': { bgColor: '#FFA07A', textColor: '#721c24' },
                    '暂停': { bgColor: '#AFEEEE', textColor: '#155724' },
                    '保护': { bgColor: '#f8d7da', textColor: '#721c24' },
                    '搁置': { bgColor: '#e2e3e5', textColor: '#383d41' },
                    '停止': { bgColor: '#B0C4DE', textColor: '#383d41' },
                    '离线': { bgColor: '#c7c7c7', textColor: '#1b1e21' },
                    '掉线': { bgColor: '#fff3cd', textColor: '#856404' },
                    '其他': { bgColor: '#D8BFD8', textColor: '#0c5460' }
                },
                showColorPicker: false,
                currentStatus: '',
                tempColor: '',
                // 新增配置文件相关属性
                configFileContent: '',
                currentConfigPath: '',
                configFileModified: false,
                // 新增：声音类型切换相关
                soundType: 'audio', // 'audio' 或 'speech'
                speechManager: new SpeechManager(), // 语音播报管理器
                // 用于跟踪已播报的报警
                announcedAlarms: new Set(),
                // 新增：声音切换状态
                isSwitchingSoundType: false,
                // 新增：设置保存状态
                isSavingSettings: false,
                // 新增：报警详情设置
                dontShowAlarmDetails: false,
                // 新增：上一次的保护计数，用于检测新报警
                lastProtectionCount: 0,
                deleteTarget: 'computer',
                deleteTargetName: '',
                deleteComputerName: '',
                deleteEquipmentCode: '',
                // 存储已删除的设备，代替原来的excludedEquipments
                deletedEquipments: {},
                // 长轮询相关：记录上次更新时间
                lastUpdateTime: null
            },
            computed: {               
                historyRecords() {
                    return this.statusRecorder.getHistoryRecords();
                },  
                
                // 优化后的过滤和排序通道方法，添加已删除设备过滤
                filteredChannels() {
                    // 如果没有数据，直接返回空数组
                    if (!this.rawData.length) return [];
                    
                    const computerNamesSet = new Set(this.monitoredComputerNames);
                    
                    // 一次性完成过滤、排序和映射操作
                    const result = this.rawData
                        .filter(item => {
                            // 检查设备是否在监控列表中
                            if (!computerNamesSet.has(item.pcName)) return false;
                            
                            // 检查设备是否被删除
                            const deleted = this.deletedEquipments[item.pcName] || [];
                            if (deleted.includes(item.equiptCode)) return false;
                            
                            // 根据视图模式过滤
                            if (this.viewMode === 'device' && this.selectedEquipment && this.selectedComputer){
                                // 设备视图：同时根据电脑名和设备号筛选
                                return item.equiptCode === this.selectedEquipment && item.pcName === this.selectedComputer;
                            }else if (this.viewMode === 'computer' && this.selectedComputer) {
                                // 电脑视图：根据电脑名筛选
                                return item.pcName === this.selectedComputer;
                            }
                            
                            // 全部通道视图：已通过前面的检查
                            return true;
                        })
                        
                        .map(channel => {
                            const key = this.statusRecorder.getChannelKey(channel);
                            const resolved = this.resolvedChannels.has(key);
                            
                            return {
                                ...this.filterChannelData(channel),
                                key: key,
                                resolved: resolved,
                                pcNum: extractNumber(channel.pcName),
                                equipNum: extractNumber(channel.equiptCode),
                                channelNum: extractNumber(channel.channelCode),
                                // 使用后端提供的curtime作为当前时间
                                curtime: channel.curtime,
                                // 每个通道所属电脑的状态
                                computerStatus: this.computerStatusMap[channel.pcName] || null
                            };
                        })
                        .sort((a, b) => {
                            if (a.pcNum !== b.pcNum) return a.pcNum - b.pcNum;
                            if (a.equipNum !== b.equipNum) return a.equipNum - b.equipNum;
                            return a.channelNum - b.channelNum;
                        });
                        
                    return result;
                },               
                monitoredComputerNames() {
                    return this.monitoredComputers.map(c => c.name);
                },
                
                // 检查是否有已删除的设备
                hasDeletedEquipments() {
                    return Object.keys(this.deletedEquipments).some(computerName => 
                        this.deletedEquipments[computerName] && 
                        this.deletedEquipments[computerName].length > 0
                    );
                },
                
                // 按电脑名排序的已删除设备列表
                sortedDeletedEquipments() {
                    // 获取所有有已删除设备的电脑名并排序
                    const sortedComputerNames = Object.keys(this.deletedEquipments)
                        .filter(computerName => this.deletedEquipments[computerName] && this.deletedEquipments[computerName].length > 0)
                        .sort(naturalSort);
                    
                    // 创建排序后的对象
                    const sortedObj = {};
                    sortedComputerNames.forEach(computerName => {
                        // 对设备号进行排序
                        const sortedEquipments = [...this.deletedEquipments[computerName]]
                            .sort((a, b) => extractNumber(a) - extractNumber(b));
                        sortedObj[computerName] = sortedEquipments;
                    });
                    
                    return sortedObj;
                }
            },
            methods: {              
                loadMonitoredComputers() {
                    try{
                        const savedComputers = localStorage.getItem(STORAGE_KEY);
                        if (savedComputers){
                            const parsed = JSON.parse(savedComputers);
                            this.monitoredComputers = parsed.map(item =>{
                                const computer = {
                                    name: item.name,
                                    expanded: false,
                                    note: item.note || ''
                                };
                                // 加载已删除的设备
                                if (item.deletedEquipments) {
                                    this.$set(this.deletedEquipments, item.name, item.deletedEquipments);
                                }
                                return computer;
                            });
                            this.persistedComputerCount = this.monitoredComputers.length;
                        }  
                    }catch (e){
                        console.error('加载保存的电脑列表失败', e);
                        this.monitoredComputers = [];
                    }
                },               
                saveMonitoredComputers(){
                    const computerData = this.monitoredComputers.map(computer => ({
                        name: computer.name,
                        note: computer.note,
                        deletedEquipments: this.deletedEquipments[computer.name] || []
                    }));
                    localStorage.setItem(STORAGE_KEY, JSON.stringify(computerData));
                },                
                
                filterChannelData(channel) {
                    // 移除updatetime字段
                    return {
                        pcName: channel.pcName,
                        equiptCode: channel.equiptCode,
                        channelCode: channel.channelCode,
                        systemStatus: channel.systemStatus,
                        curtime: channel.curtime   // 保留当前时间
                    };
                },                
                
                formatCurrentTime(date) {
                    const hours = date.getHours().toString().padStart(2, '0');
                    const minutes = date.getMinutes().toString().padStart(2, '0');
                    const seconds = date.getSeconds().toString().padStart(2, '0');
                    return `${hours}:${minutes}:${seconds}`;
                },                
                
                toggleComputer(computer) {
                    if (this.alarmDetailsVisible || this.settingsActive) return;
                    // 如果点击的是当前选中的电脑
                    if (this.selectedComputer === computer.name){
                        // 切换展开状态
                        computer.expanded = !computer.expanded;
                        this.viewMode = 'computer'; // 进入电脑视图
                    }else{
                        // 如果点击的是不同的电脑
                        this.selectedComputer = computer.name;
                        this.viewMode = 'computer'; // 进入电脑视图
                        computer.expanded = true; // 展开设备列表
                    }
                },               
                
                getEquipmentByComputer(pcName) {
                    const equipmentSet = new Set(
                        this.rawData
                            .filter(item => {
                                // 排除已删除的设备
                                const deleted = this.deletedEquipments[pcName] || [];
                                return item.pcName === pcName && !deleted.includes(item.equiptCode);
                            })
                            .map(item => item.equiptCode)
                    );
                    
                    return [...equipmentSet]
                        .map(code => ({ 
                            equiptCode: code,
                            sortKey: extractNumber(code)
                        }))
                        .sort((a, b) => a.sortKey - b.sortKey)
                        .map(item => ({
                            equiptCode: item.equiptCode
                        }));
                },                
                
                hasProtectionStatus(pcName) {                   
                    return this.rawData.some(item => 
                        item.pcName === pcName && 
                        item.systemStatus === '保护' &&
                        // 排除已删除的设备
                        !this.isEquipmentDeleted(pcName, item.equiptCode)
                    );
                },              
                // 修改：增加电脑名参数，确保只检查当前电脑下的设备
                hasProtectionForEquipment(equiptCode, pcName){
                    return this.rawData.some(item =>
                        item.equiptCode === equiptCode && 
                        item.pcName === pcName &&
                        item.systemStatus === '保护' &&
                        // 排除已删除的设备
                        !this.isEquipmentDeleted(pcName, item.equiptCode)
                    );    
                },
                
                // 检查设备是否被删除
                isEquipmentDeleted(pcName, equiptCode) {
                    const deleted = this.deletedEquipments[pcName] || [];
                    return deleted.includes(equiptCode);
                },
                
                // 修改：选择设备时记录电脑名和设备号
                selectEquipment(equipment, computer) {
                    if (this.alarmDetailsVisible || this.settingsActive) return;
                    this.viewMode = 'device';
                    this.selectedEquipment = equipment.equiptCode;
                    this.selectedComputer = computer.name; // 记录设备所属的电脑
                },               
                
                showAllChannels() {
                    this.viewMode = 'all';
                    this.selectedEquipment = null;
                    this.selectedComputer = null;
                    // 收起所有电脑的设备列表
                    this.monitoredComputers.forEach(c => c.expanded = false);
                },               
                
                addComputer() {
                    this.errorMessage = '';
                    if (!this.newComputerName) {
                        this.errorMessage = "电脑名不能为空";
                        return;
                    }                    
                    if (this.monitoredComputers.some(c => c.name === this.newComputerName)) {
                        this.errorMessage = "此电脑名已添加";
                        return;
                    }                    
                    this.monitoredComputers.push({
                        name: this.newComputerName,
                        expanded: false,
                        note: '' // 添加note属性
                    });
                    this.newComputerName = '';                  
                    this.saveMonitoredComputers();                    
                    this.startLongPolling(); // 添加新电脑后立即发起长轮询
                },              
                // 初始化删除电脑列表
                initiateDeleteComputer(pcName) {
                    this.deleteTarget = 'computer';
                    this.computerToDelete = pcName;
                    this.showDeleteConfirmation = true;
                },
                // 初始化删除设备
                initiateDeleteEquipment(computerName, equipmentCode) {
                    this.deleteTarget = 'equipment';
                    this.deleteTargetName = `${computerName} - 设备 ${equipmentCode}`;
                    this.deleteComputerName = computerName;
                    this.deleteEquipmentCode = equipmentCode;
                    this.showDeleteConfirmation = true;
                },
                // 确认删除（统一处理电脑和设备删除）
                confirmDelete() {
                    if (this.deleteTarget === 'computer') {
                        // 删除电脑逻辑（已有）
                        const index = this.monitoredComputers.findIndex(c => c.name === this.computerToDelete);
                        if (index !== -1) {
                            this.monitoredComputers.splice(index, 1);
                            // 同时删除该电脑下的所有已删除设备记录
                            this.$delete(this.deletedEquipments, this.computerToDelete);
                            
                            if (this.selectedComputer === this.computerToDelete){
                                this.selectedComputer = null;
                                this.selectedEquipment = null;
                                this.viewMode = 'all';
                            }
                        }
                        this.saveMonitoredComputers();
                    } else if (this.deleteTarget === 'equipment') {
                        // 添加到已删除设备列表
                        if (!this.deletedEquipments[this.deleteComputerName]) {
                            this.$set(this.deletedEquipments, this.deleteComputerName, []);
                        }
                        
                        // 添加到删除列表
                        if (!this.deletedEquipments[this.deleteComputerName].includes(this.deleteEquipmentCode)) {
                            this.deletedEquipments[this.deleteComputerName].push(this.deleteEquipmentCode);
                        }
                        
                        // 如果当前选中的设备是被删除的设备，则重置选中
                        if (this.selectedComputer === this.deleteComputerName && 
                            this.selectedEquipment === this.deleteEquipmentCode) {
                            this.selectedEquipment = null;
                            this.viewMode = 'computer';
                        }
                        
                        // 保存删除的设备
                        this.saveMonitoredComputers();
                        
                        // 立即刷新数据以反映变化
                        this.startLongPolling();
                    }
                    
                    this.showDeleteConfirmation = false;
                },              
                
                confirmDeleteComputer() {
                    this.confirmDelete();
                },
                
                // 恢复已删除的设备
                restoreEquipment(computerName, equipmentCode) {
                    if (this.deletedEquipments[computerName]) {
                        const index = this.deletedEquipments[computerName].indexOf(equipmentCode);
                        if (index !== -1) {
                            // 从已删除列表中移除
                            this.deletedEquipments[computerName].splice(index, 1);
                            
                            // 如果该电脑下已没有删除的设备，清除该电脑的记录
                            if (this.deletedEquipments[computerName].length === 0) {
                                this.$delete(this.deletedEquipments, computerName);
                            }
                            
                            // 保存更改
                            this.saveMonitoredComputers();
                            
                            // 刷新数据
                            this.startLongPolling();
                        }
                    }
                },
                
                // 优化：切换声音类型，等待当前播放完成
                async toggleSoundType() {
                    // 如果正在切换，直接返回
                    if (this.isSwitchingSoundType) return;
                    
                    this.isSwitchingSoundType = true;
                    
                    try {
                        // 检查当前是否有正在播放的内容
                        if (this.soundType === 'audio' && this.alarmPlaying) {
                            // 等待音频播放完成（或直接停止）
                            this.stopAlarm();
                        } else if (this.soundType === 'speech' && this.speechManager.isActive()) {
                            // 等待语音播报完成
                            while (this.speechManager.isActive()) {
                                await new Promise(resolve => setTimeout(resolve, 100));
                            }
                        }
                        
                        // 执行切换
                        this.soundType = this.soundType === 'audio' ? 'speech' : 'audio';
                        localStorage.setItem(SOUND_TYPE_KEY, this.soundType);
                        
                        // 切换后根据需要启动新的播放方式
                        if (this.activeProtectionCount > 0) {
                            if (this.soundType === 'audio') {
                                this.playAlarm();
                            } else {
                                this.announceNewAlarms();
                            }
                        }
                    } finally {
                        // 无论如何都要重置切换状态
                        this.isSwitchingSoundType = false;
                    }
                },
                
                playAlarm() {
                    if (this.soundType !== 'audio' || this.activeProtectionCount === 0) return;
                    if (this.alarmAudio && !this.alarmPlaying) {
                        this.alarmAudio.play().catch(e => {
                            console.log("自动播放被阻止，但已在主进程中设置权限", e);
                        });
                        this.alarmPlaying = true;
                    }
                },                
                
                stopAlarm() {
                    if (this.soundType === 'audio' && this.alarmAudio && this.alarmPlaying) {
                        this.alarmAudio.pause();
                        this.alarmAudio.currentTime = 0;
                        this.alarmPlaying = false;
                    }
                },
                
                // 优化：语音播报新报警，直接从当前数据获取，只播报真正处于保护状态的通道
                announceNewAlarms() {
                    if (this.soundType !== 'speech' || this.activeProtectionCount === 0) return;
                    
                    // 直接从当前数据中获取所有处于保护状态且未被解决的通道
                    const activeAlarms = this.rawData
                        .filter(channel => {
                            const key = this.statusRecorder.getChannelKey(channel);
                            // 排除已删除的设备
                            if (this.isEquipmentDeleted(channel.pcName, channel.equiptCode)) {
                                return false;
                            }
                            return channel.systemStatus === '保护' && !this.resolvedChannels.has(key);
                        });
                    
                    // 为每个活跃报警添加到播报队列（如果尚未添加）
                    activeAlarms.forEach(channel => {
                        const alarmId = this.statusRecorder.getChannelKey(channel);
                        if (!this.announcedAlarms.has(alarmId)) {
                            const message = `请注意：${channel.pcName}，设备${channel.equiptCode}，通道${channel.channelCode}处于保护状态`;
                            this.speechManager.addToQueue(message, alarmId);
                            this.announcedAlarms.add(alarmId);
                        }
                    });
                },
                
                // 消除所有报警
                resolveAllAlarms() {
                    // 将所有保护状态通道标记为已解决
                    const newResolved = new Set(this.resolvedChannels);
                    
                    this.rawData.forEach(channel => {
                        // 排除已删除的设备
                        if (this.isEquipmentDeleted(channel.pcName, channel.equiptCode)) {
                            return;
                        }
                        
                        if (channel.systemStatus === '保护') {
                            const key = this.statusRecorder.getChannelKey(channel);
                            if (!newResolved.has(key)) {
                                newResolved.add(key);
                            }
                        }
                    });
                    
                    this.resolvedChannels = newResolved;
                    this.resolvedAll = true;
                    
                    // 清除语音播报的重复计时器
                    this.speechManager.clearAllAlarms();
                    
                    // 停止所有声音
                    this.stopAlarm();
                    this.speechManager.stop();
                    
                    // 清除已播报标记
                    this.announcedAlarms.clear();
                    
                    // 5秒后重置按钮状态
                    setTimeout(() => {
                        this.resolvedAll = false;
                    }, 5000);
                },
                
                // 检查报警状态
                checkAlarmStatus() {
                    const previousCount = this.activeProtectionCount;
                    const activeProtections = [];
                    const monitoredNames = new Set(this.monitoredComputerNames); // 获取当前监控的设备名集合
                    // 统计所有未解决的保护状态通道
                    this.rawData.forEach(channel => {
                        // 新增：检查设备是否仍在监控列表中
                        if(!monitoredNames.has(channel.pcName))return;
                        
                        // 检查设备是否被删除
                        if (this.isEquipmentDeleted(channel.pcName, channel.equiptCode)) {
                            return;
                        }
                        
                        if (channel.systemStatus === '保护') {
                            const key = this.statusRecorder.getChannelKey(channel);
                            if (!this.resolvedChannels.has(key)) {
                                activeProtections.push(channel);
                            } else {
                                // 使用通道的唯一标识符作为报警ID
                                const alarmId = key;
                                this.speechManager.clearAlarm(alarmId);
                                this.announcedAlarms.delete(alarmId);
                            }
                        } else {
                            // 当通道状态从保护变为非保护时，清除语音播报
                            const key = this.statusRecorder.getChannelKey(channel);
                            if (this.announcedAlarms.has(key)) {
                                this.speechManager.clearAlarm(key);
                                this.announcedAlarms.delete(key);
                            }
                        }
                    });
                    
                    this.activeProtectionCount = activeProtections.length;
                    
                    // 检查是否有新的报警
                    const hasNewAlarms = this.activeProtectionCount > 0 && 
                                        (this.activeProtectionCount > this.lastProtectionCount || 
                                         this.statusRecorder.getNewAlarms().size > 0);
                    
                    // 更新最后一次保护计数
                    this.lastProtectionCount = this.activeProtectionCount;
                    
                    // 处理报警详情自动显示
                    if (hasNewAlarms && !this.dontShowAlarmDetails) {
                        this.alarmDetailsVisible = true;
                    }
                    
                    // 清除新报警标记
                    if (this.alarmDetailsVisible) {
                        this.statusRecorder.clearNewAlarms();
                    }
                    
                    if (this.activeProtectionCount > 0) {
                        if (this.soundType === 'audio') {
                            this.playAlarm();
                        } else {
                            this.announceNewAlarms();
                        }
                    } else {
                        this.stopAlarm();
                        this.speechManager.stop();
                        this.speechManager.clearAllAlarms();
                        this.announcedAlarms.clear();
                    }
                },                   
                // 更新电脑状态映射
                updateComputerStatusMap() {
                    // 重置状态映射
                    const newStatusMap = {};
                    
                    // 遍历所有监控的电脑
                    this.monitoredComputers.forEach(computer => {
                        const pcName = computer.name;
                        
                        // 检查该电脑是否有数据返回
                        const hasComputerData = this.rawData.some(item => 
                            item.pcName === pcName && 
                            !this.isEquipmentDeleted(pcName, item.equiptCode)
                        );
                        
                        if (!hasComputerData) {
                            // 该电脑完全无数据 - 掉线状态
                            newStatusMap[pcName] = '掉线';
                        } else {
                            // 检查该电脑是否有任何通道状态为掉线
                            const hasDisconnected = this.rawData.some(
                                item => item.pcName === pcName && 
                                item.systemStatus === '掉线' &&
                                !this.isEquipmentDeleted(pcName, item.equiptCode)
                            );
                            
                            // 检查该电脑是否有任何通道状态为离线
                            const hasOffline = this.rawData.some(
                                item => item.pcName === pcName && 
                                item.systemStatus === '离线' &&
                                !this.isEquipmentDeleted(pcName, item.equiptCode)
                            );
                            
                            if (hasDisconnected) {
                                newStatusMap[pcName] = '掉线';
                            } else if (hasOffline) {
                                newStatusMap[pcName] = '离线';
                            } else {
                                newStatusMap[pcName] = null;
                            }
                        }
                    });
                    
                    // 更新状态映射
                    this.computerStatusMap = newStatusMap;
                    
                    // 更新每台电脑的状态 (用于在备注右侧显示)
                    this.monitoredComputers.forEach(computer => {
                        computer.status = this.computerStatusMap[computer.name] || null;
                    });
                },
                
                // 长轮询请求数据
                fetchData() {
                    if (this.isPolling) return; // 防止重复请求
                    
                    const computerNames = this.monitoredComputers.map(c => c.name);
                    if (computerNames.length === 0) {
                        this.rawData = [];
                        this.lastRefreshTime = this.formatCurrentTime(new Date());
                        this.checkAlarmStatus();
                        return;
                    }                   
                    
                    this.isPolling = true;
                    
                    // 使用固定的API地址，发送上次更新时间
                    axios.post(DEFAULT_API_URL, {
                        computers: computerNames,
                        since_time: this.lastUpdateTime // 发送上次更新时间
                    }, { 
                        timeout: this.settings.longPollTimeout * 1000 + 1000 // 超时时间比服务器设置长1秒
                    })
                    .then(response => {
                        if (response.data.success) {
                            const newData = response.data.data;
                            
                            // 如果有新数据，更新最后更新时间
                            if (newData && newData.length > 0) {
                                this.lastUpdateTime = new Date().toLocaleString('zh-CN', { 
                                    year: 'numeric', 
                                    month: '2-digit', 
                                    day: '2-digit', 
                                    hour: '2-digit', 
                                    minute: '2-digit', 
                                    second: '2-digit',
                                    hour12: false
                                }).replace(',', '');
                            }
                            
                            // 先更新电脑状态，再处理通道数据
                            this.rawData = newData;
                            this.updateComputerStatusMap();
                            
                            // 清除状态已改变的通道标记
                            const newResolved = new Set();
                            this.resolvedChannels.forEach(key => {
                                const channel = newData.find(ch => 
                                    this.statusRecorder.getChannelKey(ch) === key
                                );
                                // 如果状态还是保护状态，保留标记
                                if (channel && channel.systemStatus === '保护') {
                                    newResolved.add(key);
                                } else if (channel) {
                                    // 状态已从保护变为其他状态，清除语音播报
                                    this.speechManager.clearAlarm(key);
                                    this.announcedAlarms.delete(key);
                                }
                            });
                            this.resolvedChannels = newResolved;
                            
                            // 处理通道状态更新
                            newData.forEach(channel => {
                                // 排除已删除的设备
                                if (this.isEquipmentDeleted(channel.pcName, channel.equiptCode)) {
                                    return;
                                }
                                
                                const result = this.statusRecorder.updateChannelStatus(channel);
                                // 如果状态从保护变为其他状态，清除语音播报
                                if (result.statusChanged && result.fromProtection) {
                                    const key = this.statusRecorder.getChannelKey(channel);
                                    this.speechManager.clearAlarm(key);
                                    this.announcedAlarms.delete(key);
                                }
                            });                         
                            
                            this.checkAlarmStatus();
                            this.lastRefreshTime = this.formatCurrentTime(new Date());
                            this.errorMessage = '';
                        } else {
                            this.errorMessage = response.data.errorInfo || "获取数据失败";
                            this.lastRefreshTime = this.formatCurrentTime(new Date());
                        }
                    })
                    .catch(error => {
                        console.error('数据获取失败:', error);
                        this.errorMessage = "连接服务器失败，请检查设置";
                        this.lastRefreshTime = this.formatCurrentTime(new Date());
                    })
                    .finally(() => {
                        this.isPolling = false;
                        // 立即发起下一次长轮询
                        this.startLongPolling();
                    });
                },
                
                // 开始长轮询
                startLongPolling() {
                    if (!this.isPolling) {
                        this.fetchData();
                    }
                },
                
                // 停止长轮询
                stopLongPolling() {
                    // 由于axios没有直接的取消方法，这里设置标志位
                    this.isPolling = false;
                },
                
                // 新增：切换报警详情显示状态
                toggleAlarmDetails() {
                    this.alarmDetailsVisible = !this.alarmDetailsVisible;
                    // 如果关闭时勾选了不再显示，则保存设置
                    if (!this.alarmDetailsVisible) {
                        localStorage.setItem(ALARM_DETAILS_KEY, this.dontShowAlarmDetails.toString());
                    }
                },              
                
                toggleSettingsPanel() {
                    this.settingsActive = !this.settingsActive;
                },               
                
                closeAllPanels() {
                    this.alarmDetailsVisible = false;
                    this.settingsActive = false;
                    this.showDeleteConfirmation = false;
                    this.showColorPicker = false;
                    // 保存报警详情设置
                    localStorage.setItem(ALARM_DETAILS_KEY, this.dontShowAlarmDetails.toString());
                },               
                
                // 优化：保存设置，更新长轮询超时时间
                async saveSettings() {
                    // 如果正在保存，直接返回
                    if (this.isSavingSettings) return;
                    
                    this.isSavingSettings = true;
                    
                    try {
                        // 验证长轮询超时时间的有效性
                        if (this.settings.longPollTimeout < 5 || this.settings.longPollTimeout > 60) {
                            alert('长轮询超时时间必须在5-60秒之间');
                            return;
                        }
                        
                        // 保存设置
                        this.longPollTimeout = this.settings.longPollTimeout;
                        
                        // 保存到本地存储
                        localStorage.setItem('monitorSettings', JSON.stringify(this.settings));
                        localStorage.setItem(STATUS_COLORS_KEY, JSON.stringify(this.statusColors));

                        // 处理配置文件保存
                        if (this.configFileModified && this.configFileContent.trim()){
                            let savePath = this.currentConfigPath;
                            // 如果没有当前路径，打开保存对话框
                            if (!savePath){
                                const { result: newPath, error } = await window.electronAPI.showSaveDialog();
                                if (error) throw error;
                                if (!newPath){
                                    // 用户取消了保存对话框，仍然提示主设置已保存
                                    alert('系统设置已保存！配置文件未保存');
                                    return;
                                }
                                savePath = newPath;
                            }
                            // 写入文件
                            const { error: writeError } = await window.electronAPI.writeFile(savePath, this.configFileContent);
                            if (writeError){
                                throw writeError;
                            }
                            // 更新UI
                            this.currentConfigPath = savePath;
                            this.configFileModified = false;
                            this.sendStatusMessage = '配置文件保存成功！';
                        }
                        
                        // 关闭设置面板
                        this.settingsActive = false;
                        
                        alert('所有设置已保存成功！');
                    } catch (e) {
                        console.error('保存设置出错:', e);
                        alert(`保存设置出错: ${e.message || '请检查输入参数'}`);
                    } finally {
                        // 无论如何都要重置保存状态
                        this.isSavingSettings = false;
                        // 清除状态消息
                        setTimeout(() =>{
                            this.sendStatusMessage = '';
                        },3000);
                    }
                },               
                
                initAlarmAudio() {
                    this.alarmAudio = document.getElementById('alarm-sound');
                    if (this.alarmAudio) {
                        this.alarmAudio.volume = 1;
                        // 尝试加载时播放一点然后立即暂停，以获取自动播放权限
                        this.alarmAudio.play().then(() => {
                            this.alarmAudio.pause();
                            this.alarmAudio.currentTime = 0;
                        }).catch(e => {
                            console.log("初始化音频播放失败，但已在主进程中设置权限", e);
                        });
                    }
                },               
                
                loadSettings() {
                    try {
                        const savedSettings = localStorage.getItem('monitorSettings');
                        if (savedSettings) {
                            this.settings = JSON.parse(savedSettings);
                            this.longPollTimeout = this.settings.longPollTimeout;
                        }
                        
                        // 加载状态颜色配置
                        const savedColors = localStorage.getItem(STATUS_COLORS_KEY);
                        if (savedColors) {
                            this.statusColors = JSON.parse(savedColors);
                        }
                        
                        // 新增：加载声音类型设置
                        const savedSoundType = localStorage.getItem(SOUND_TYPE_KEY);
                        if (savedSoundType) {
                            this.soundType = savedSoundType;
                        }
                        
                        // 新增：加载报警详情设置
                        const savedAlarmDetails = localStorage.getItem(ALARM_DETAILS_KEY);
                        if (savedAlarmDetails) {
                            this.dontShowAlarmDetails = savedAlarmDetails === 'true';
                        }
                    } catch (e) {
                        console.error('加载设置失败', e);
                    }
                },
                // 新增：获取当前视图模式的名称
                getViewModeName(){
                    if (this.viewMode === 'all') return '全部通道视图';
                    if (this.viewMode === 'computer') return '电脑视图';
                    if (this.viewMode === 'device') return '设备视图';
                    return '';
                },
                
                //  新增拖动排序方法
                onDragStart(e, index) {
                    this.isDragging = true;
                    this.dragStartIndex = index;
                    
                    // 设置拖动数据
                    e.dataTransfer.setData("text/plain", index.toString());
                    e.dataTransfer.effectAllowed = "move";
                    
                    // 创建拖动代理元素（在鼠标指针处显示的视觉反馈）
                    const dragProxy = document.createElement('div');
                    dragProxy.className = 'drag-proxy';
                    
                    // 克隆原始元素内容
                    const item = e.currentTarget;
                    const clone = item.cloneNode(true);
                    clone.style.opacity = 0.8;
                    clone.style.transform = '';
                    dragProxy.appendChild(clone);
                    
                    // 添加到body中
                    document.body.appendChild(dragProxy);
                    e.dataTransfer.setDragImage(dragProxy, 0, 0);
                    
                    // 添加阴影效果
                    item.classList.add('drag-shadow');
                    
                    // 设置延时清除代理（避免拖动结束时太快清除）
                    this.dragProxy = dragProxy;
                    this.dragProxyTimer = setTimeout(() => {
                        if (dragProxy && dragProxy.parentNode) {
                            dragProxy.parentNode.removeChild(dragProxy);
                        }
                    }, 300);
                },
                onDragOver(e, index) {
                    if (!this.isDragging) return;
                    
                    e.preventDefault();
                    
                    const item = e.currentTarget;
                    const rect = item.getBoundingClientRect();
                    const mouseY = e.clientY;
                    const itemMidY = rect.top + rect.height / 2;
                    
                    // 根据鼠标位置判断是上方还是下方
                    if (mouseY < itemMidY) {
                        this.dragDirection = 'top';
                        item.classList.add('drag-over-top');
                        item.classList.remove('drag-over-bottom');
                    } else {
                        this.dragDirection = 'bottom';
                        item.classList.add('drag-over-bottom');
                        item.classList.remove('drag-over-top');
                    }
                    
                    this.dragOverIndex = index;
                },
                onDragEnter(e, index) {
                    e.preventDefault();
                    if (this.isDragging) {
                        this.dragOverIndex = index;
                    }
                },
                
                onDragLeave(e, index) {
                    // 移除所有视觉指示
                    const item = e.currentTarget;
                    item.classList.remove('drag-over-top');
                    item.classList.remove('drag-over-bottom');
                },
                onDrop(e, index) {
                    e.preventDefault();
                    
                    const dragItemIndex = this.dragStartIndex;
                    const dropItemIndex = this.dragOverIndex;
                    const direction = this.dragDirection;
                    
                    if (dragItemIndex === dropItemIndex || dragItemIndex === -1 || dropItemIndex === -1) {
                        this.resetDragStyles();
                        return;
                    }
                    
                    // 根据拖动方向和位置调整索引
                    let newIndex;
                    if (dragItemIndex < dropItemIndex && direction === 'top') {
                        newIndex = dropItemIndex - 1;
                    } else if (dragItemIndex > dropItemIndex && direction === 'bottom') {
                        newIndex = dropItemIndex + 1;
                    } else {
                        newIndex = direction === 'top' ? dropItemIndex - 1 : dropItemIndex;
                    }
                    
                    // 确保索引在有效范围内
                    newIndex = Math.max(0, Math.min(this.monitoredComputers.length - 1, newIndex));
                    
                    // 交换位置
                    const dragItem = this.monitoredComputers[dragItemIndex];
                    this.monitoredComputers.splice(dragItemIndex, 1);
                    this.monitoredComputers.splice(newIndex, 0, dragItem);
                    
                    // 保存新顺序
                    this.saveMonitoredComputers();
                    
                    // 重置拖动样式
                    this.resetDragStyles();
                    
                    // 恢复原始布局
                    setTimeout(() => {
                        this.$nextTick(() => {
                            this.resetDragStyles();
                        });
                    }, 100);
                },
                onDragEnd(e, index) {
                    this.isDragging = false;
                    this.resetDragStyles();
                    
                    // 清除代理元素
                    clearTimeout(this.dragProxyTimer);
                    if (this.dragProxy && this.dragProxy.parentNode) {
                        this.dragProxy.parentNode.removeChild(this.dragProxy);
                        this.dragProxy = null;
                    }
                    
                    // 从拖动项移除阴影样式
                    const dragItems = document.querySelectorAll('.drag-shadow');
                    dragItems.forEach(item => item.classList.remove('drag-shadow'));
                },
                resetDragStyles() {
                    // 移除所有视觉指示
                    const topItems = document.querySelectorAll('.drag-over-top');
                    const bottomItems = document.querySelectorAll('.drag-over-bottom');
                    
                    topItems.forEach(item => item.classList.remove('drag-over-top'));
                    bottomItems.forEach(item => item.classList.remove('drag-over-bottom'));
                    
                    this.dragStartIndex = -1;
                    this.dragOverIndex = -1;
                    this.dragDirection = null;
                },
                
                // ====== 新增状态颜色自定义方法 ======
                openColorPicker(status) {
                    this.currentStatus = status;
                    this.tempColor = this.statusColors[status].bgColor;
                    this.showColorPicker = true;
                },
                
                saveColorChange() {
                    this.statusColors[this.currentStatus].bgColor = this.tempColor;                   
                    // 自动计算文字颜色（深色背景用白色文字，浅色背景用黑色文字）
                    const hex = this.tempColor.replace('#', '');
                    const r = parseInt(hex.substr(0, 2), 16);
                    const g = parseInt(hex.substr(2, 2), 16);
                    const b = parseInt(hex.substr(4, 2), 16);                   
                    // 计算亮度（0-255）
                    const brightness = (r * 299 + g * 587 + b * 114) / 1000;                   
                    // 根据亮度设置文字颜色
                    this.statusColors[this.currentStatus].textColor = brightness > 128 ? '#000' : '#fff';                    
                    this.showColorPicker = false;
                },               
                cancelColorChange() {
                    this.showColorPicker = false;
                },              
                getStatusStyle(status) {
                    // 将状态映射到状态列表中的类别
                    let statusCategory = '其他';
                    
                    if (this.statusList.includes(status)) {
                        statusCategory = status;
                    }                   
                    const colorConfig = this.statusColors[statusCategory];                   
                    return {
                        backgroundColor: colorConfig.bgColor,
                        color: colorConfig.textColor
                    };
                },
                // 新增配置文件操作方法
                async openConfigFile() {
                    try {
                        // 修正：正确解析返回结果
                        const { result: filePath, error } = await window.electronAPI.openFileDialog();
                        if (error) {
                            throw error;
                        }
                        if (!filePath) return; // 用户取消选择
                        
                        // 读取文件内容
                        const { result: content, error: readError } = await window.electronAPI.readFile(filePath);
                        if (readError) {
                            throw readError;
                        }
                        
                        // 更新UI
                        this.configFileContent = content;
                        this.currentConfigPath = filePath;
                        this.configFileModified = false;
                        this.sendStatusMessage = '配置文件加载成功！';
                    } catch (error) {
                        console.error('打开配置文件失败:', error);
                        this.sendStatusMessage = `打开配置文件失败: ${error.message || error}`;
                    } finally {
                        setTimeout(() => {
                            this.sendStatusMessage = '';
                        }, 3000);
                    }
                },
                // 加载上次使用的配置文件路径
                loadLastConfigPath() {
                    const lastPath = localStorage.getItem('lastConfigPath');
                    if (lastPath) {
                        this.currentConfigPath = lastPath;
                    }
                },
                // 新增：请求语音合成权限
                async requestSpeechPermission() {
                    try {
                        await window.electronAPI.requestSpeechPermission();
                        console.log('语音合成权限已获取');
                    } catch (error) {
                        console.error('获取语音合成权限失败:', error);
                    }
                }
            },
            watch: {
                // 监听配置文件内容变化
                configFileContent(newVal, oldVal) {
                    if (newVal !== oldVal) {
                        this.configFileModified = true;
                    }
                },
                // 监听报警详情设置变化
                dontShowAlarmDetails(newVal) {
                    localStorage.setItem(ALARM_DETAILS_KEY, newVal.toString());
                }
            },
            mounted() { 
                // 加载上次使用的配置文件路径
                this.loadLastConfigPath();              
                this.initAlarmAudio();            
                this.loadSettings();              
                this.loadMonitoredComputers();
                this.startLongPolling(); // 启动长轮询
                // 预初始化拖动状态
                this.resetDragStyles();
                
                // 初始检查保护状态
                this.$nextTick(() => {
                    this.checkAlarmStatus();
                    // 请求语音权限
                    this.requestSpeechPermission();
                });
            },
            beforeDestroy() {            
                localStorage.setItem('monitorSettings', JSON.stringify(this.settings));
                // 保存声音类型设置
                localStorage.setItem(SOUND_TYPE_KEY, this.soundType);
                // 保存报警详情设置
                localStorage.setItem(ALARM_DETAILS_KEY, this.dontShowAlarmDetails.toString());
                
                // 停止长轮询
                this.stopLongPolling();
                
                if (this.alarmAudio) {
                    this.alarmAudio.pause();
                }
                // 停止语音播报
                this.speechManager.stop();
                this.speechManager.clearAllAlarms();
                
                // 移除拖动代理元素（防止内存泄漏）
                if (this.dragProxy && this.dragProxy.parentNode) {
                    this.dragProxy.parentNode.removeChild(this.dragProxy);
                }
            }
        });
    </script>
    <script src="../assets/renderer.js"></script>
</body>
</html>
